#include "stdafx.h"

#include "video/window.h"
#include "core/event.h"
#include "core/kernel.h"
#include "core/logger.h"
#include "util/check_glerror.h"

namespace natrium {
	namespace video {
		Window::Window(const std::string& name):
			util::Named(name),
			mTitle(name)
		{
			mWidth = 1024;
			mHeight = 786;

			mFullscreen = false;
			mAutoSizeWindow = false;

			mScreenAspectRatio = 1.0f;
			mScreenAspectType = UNKNOWN_ASPECT;
		}

		Window::~Window() {
		}

		void Window::create() {
			glfwGetDesktopMode(&mDesktopMode);

			mScreenAspectRatio = static_cast<float>(mDesktopMode.Width) / static_cast<float>(mDesktopMode.Height);
		
			int screenPercentile = static_cast<int>(mScreenAspectRatio * 100);
		
			switch (screenPercentile) {
			case 177:
				mScreenAspectType = ASPECT_16_9;
				break;

			case 160:
				mScreenAspectType = ASPECT_16_10;
				break;
		
			case 133:
				mScreenAspectType = ASPECT_4_3;
				break;

			default:
				mScreenAspectType = UNKNOWN_ASPECT;
			}

			if (mAutoSizeWindow) {
				mWidth = mDesktopMode.Width;
				mHeight = mDesktopMode.Height;
			}

			assert(mHeight > 0);
			mWindowAspectRatio = static_cast<float>(mWidth) / static_cast<float>(mHeight);

			int windowPercentile = static_cast<int>(mWindowAspectRatio * 100);
		
			switch (windowPercentile) {
			case 177:
				mWindowAspectType = ASPECT_16_9;
				break;

			case 160:
				mWindowAspectType = ASPECT_16_10;
				break;

			case 133:
				mWindowAspectType = ASPECT_4_3;
				break;

			default:
				mWindowAspectType = UNKNOWN_ASPECT;
			}

			//now, attempt to create the window
			glfwOpenWindowHint(GLFW_REFRESH_RATE, 0); //default refresh rate
			glfwOpenWindowHint(GLFW_ACCUM_RED_BITS, 0); //no accumulation buffer bits
			glfwOpenWindowHint(GLFW_ACCUM_GREEN_BITS, 0); //no accumulation buffer bits
			glfwOpenWindowHint(GLFW_ACCUM_BLUE_BITS, 0); //no accumulation buffer bits
			glfwOpenWindowHint(GLFW_ACCUM_ALPHA_BITS, 0); //no accumulation buffer bits
			glfwOpenWindowHint(GLFW_AUX_BUFFERS, 0); //no auxiliary buffers
			glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE); //disallow window resizing (does nothing in fullscreen mode)
			glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 0); //disable multisampling
			glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4); //Create an opengl 4.2 window
			glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2);
			glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //disable legacy functionality
			glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_FALSE); //don't create a debug context
			glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //use the 'core' profile

			glfwOpenWindow(
				mWidth,
				mHeight,
				8, 8, 8, 8, //32 bits color
				24, 8, //24 bits depth buffer and 8 bits stencil
				mFullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW
			);

			glfwSetWindowTitle(getName().c_str());

			if (mFullscreen)
				glfwDisable(GLFW_MOUSE_CURSOR);

			glfwSwapInterval(0); //disable vertical sync

			glfwSetWindowCloseCallback(&Window::glfwCloseCallback);
		}

		void Window::destroy() {
			if (mFullscreen)
				glfwEnable(GLFW_MOUSE_CURSOR);

			glfwCloseWindow();
		}

		Window::eScreenAspect Window::getScreenAspect() const {
			assert(mIsInitialized);
			return mScreenAspectType;
		}

		float Window::getScreenAspectRatio() const {
			assert(mIsInitialized);
			return mScreenAspectRatio;
		}

		float Window::getWindowAspectRatio() const {
			return mWindowAspectRatio;
		}

		int Window::glfwCloseCallback() {
			core::EventChannel chan;
			chan.broadcast(core::Kernel::StopEvent());
			return 0;
		}

		unsigned int Window::getWidth() const {
			return mWidth;
		}

		unsigned int Window::getHeight() const {
			return mHeight;
		}
	}
}